package com.marvels.approve.loan.service.impl;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.dragon.app.ykd.constant.ApplyNode;
import com.dragon.app.ykd.service.AcLoanApplyNodeService;
import com.dragon.app.ykd.service.ClientAppService;
import com.dragon.loan.entity.AcLoanApplyInfo;
import com.dragon.loan.service.LoanInfoIDragonService;
import com.github.pagehelper.util.StringUtil;
import com.marvels.approve.common.service.ApproveIStateDetailedService;
import com.marvels.approve.common.service.McamLoanApplyInfoCommonService;
import com.marvels.approve.common.service.ProductConsumerService;
import com.marvels.approve.consum.ApproveConsumerFinancialApi;
import com.marvels.approve.credit.dao.McamAttachmentInfoDao;
import com.marvels.approve.loan.dto.FundSourceDTO;
import com.marvels.approve.loan.dto.LoanCheckingDTO;
import com.marvels.approve.loan.dto.McamLoanApplyInfoDTO;
import com.marvels.approve.loan.service.ILoanCheckingService;
import com.marvels.approve.loan.service.IMcamLoanApplyInfoService;
import com.marvels.approve.manager.dto.OpinionDTO;
import com.marvels.approve.manager.dto.OpinionTypeDTO;
import com.marvels.approve.manager.service.IOpinionService;
import com.marvels.approve.manager.service.IOpinionTypeService;
import com.marvels.approve.process.dao.ILoanApplyCaseDao;
import com.marvels.approve.process.dao.McamResignStateMsgDao;
import com.marvels.approve.process.dto.CompleteProcessDTO;
import com.marvels.approve.process.dto.LoanApplyCaseDTO;
import com.marvels.approve.process.dto.McamResignStateMsgDTO;
import com.marvels.approve.process.dto.McptProductInfoDTO;
import com.marvels.approve.process.dto.ProcessApproveDTO;
import com.marvels.approve.process.service.IProcessService;
import com.marvels.common.constants.CaseNodeConstant;
import com.marvels.common.constants.LoanStateConstant;
import com.marvels.common.constants.MarvelsConstant;
import com.marvels.common.dto.UserDTO;
import com.marvels.common.exception.MarvelsBusinessException;
import com.marvels.common.utils.CacheUtils;
import com.marvels.common.utils.MarvelsLogUtil;

@Service
public class LoanCheckingServiceImpl implements ILoanCheckingService {
	@Autowired
	private ILoanApplyCaseDao loanApplyCaseDao ;
	@Autowired
	private IOpinionTypeService opinionTypeService ;
	@Autowired
	private IMcamLoanApplyInfoService mcamLoanApplyInfoService;
	@Autowired
	private IProcessService processService;
	@Autowired
	private McamAttachmentInfoDao mcamAttachmentInfoDao;
	@Autowired
	private ApproveIStateDetailedService stateDetailedService;
	@Autowired
	private IOpinionService opinionService;
	@Autowired
	private McamLoanApplyInfoCommonService mcamLoanApplyInfoCommonService;
	@Autowired
	private ApproveConsumerFinancialApi consumerFinancialApi;
	@Autowired
	private ProductConsumerService productConsumerService;
	@Autowired
	private LoanInfoIDragonService loanInfoIDragonService;
	@Autowired
	private ClientAppService clientAppService;
	@Autowired
	private AcLoanApplyNodeService acLoanApplyNodeService;
	@Value("${loanid.prefix}")
	private String loanidPrefix;
	@Autowired
	private McamResignStateMsgDao mcamResignStateMsgDao;
	@Override
	public LoanCheckingDTO findChecking(LoanCheckingDTO loanChecking) throws MarvelsBusinessException {
		//查询征信阶段信息
		if(loanChecking == null || loanChecking.getLoanId() == null ) {
			throw new MarvelsBusinessException("查询征信阶段信息条件不能为空"+loanChecking);
		}
		String loanId = loanChecking.getLoanId();
		LoanApplyCaseDTO loanApplyCase = loanApplyCaseDao.getEntityByLoanId(loanId);
		if(loanApplyCase==null) {
			throw new MarvelsBusinessException("工单不存在loanId:"+loanId);
		}
		if(!CaseNodeConstant.WOCHECKING.getCode().equals(loanApplyCase.getCurNodeCode())) {
			throw new MarvelsBusinessException("工单节点在"+loanApplyCase.getCurNodeCode()+"不正确,loanId:"+loanId);
		}
		UserDTO user = CacheUtils.getCacheUser();
		String userCode = user.getUserCode();
		if(userCode==null || !userCode.equals(loanApplyCase.getAssignee())) {
			throw new MarvelsBusinessException("工单属于"+loanApplyCase.getAssignee()+",请确认工单所属,loanId:"+loanId);
		}
		loanChecking.setLoanApplyCase(loanApplyCase);
		//初始化类型选项
		Map<Integer,List<OpinionTypeDTO>> opinionTypes = this.opinionTypeService.getOpinionTypes(CaseNodeConstant.WOCHECKING.getCode());
		loanChecking.setOpinionTypes(opinionTypes);
		//日志加意见
		//LOG
		List<OpinionDTO>  logs = opinionService.selectApproveResultLogByLoanId(loanApplyCase);
		loanChecking.setLogs(logs);
		// OPINOIN
		List<OpinionDTO> opinions = opinionService.selectOpinionsByCaseVersion(loanApplyCase);
		loanChecking.setOpinions(opinions);
		return loanChecking;
	}

	@Override
	public LoanCheckingDTO saveChecking(LoanCheckingDTO loanChecking) throws MarvelsBusinessException {
		// 保存征信复核信息
		String loanId = loanChecking.getLoanId();
		LoanApplyCaseDTO loanApplyCase = getLoanApplyCase(loanId);

		McamLoanApplyInfoDTO loanApplyInfo = getLoanApplyInfo(loanId);
		//保存相关日志
		//LoanApplyCaseDTO loanApplyCase , McamLoanApplyInfoDTO loanApplyInfo,
//		List<OpinionTypeDTO> processOpinions,String violationOpinion,List<OpinionTypeDTO> returnAppOpinions,List<OpinionTypeDTO> checkOpinionTypes,
//		String opinionContent , String violationOptionContent ,String returnAppOpinionContent
		opinionService.saveOpinions(loanApplyCase,loanApplyInfo, loanChecking.getProcessResult()
				,loanChecking.getProcessOpinions(),loanChecking.getViolationOpinion(),loanChecking.getReturnAppOpinions(),loanChecking.getCheckOpinionTypes()
				,loanChecking.getCheckOpinionContent(),loanChecking.getViolationOptionContent(),loanChecking.getReturnAppOpinionContent());
		return loanChecking;
	}
//	//保存意见--看看有没有必要挪到意见服务中
//	private LoanCheckingDTO saveCheckingOpinion(LoanCheckingDTO loanChecking , LoanApplyCaseDTO loanApplyCase , McamLoanApplyInfoDTO loanApplyInfo) throws MarvelsBusinessException {
//		//保存复核意见
//		List<OpinionTypeDTO> processOpinions = loanChecking.getProcessOpinions();
//		if(processOpinions!=null && processOpinions.size() >0) {
//			for (OpinionTypeDTO processOpinion:processOpinions) {
//				initOpinion(loanApplyCase,processOpinion.getOpinionTypeCode(),loanChecking.getCheckOpinionContent());
//			}
//		}
//		//违例
//		String violationOpinion = loanChecking.getViolationOpinion();
//		if(!StringUtils.isBlank(violationOpinion)) {
//			initOpinion(loanApplyCase,violationOpinion,loanChecking.getViolationOptionContent());
//		}
//		//退单到前端APP类型
//		List<OpinionTypeDTO> returnAppOpinions = loanChecking.getReturnAppOpinions();
//		if(returnAppOpinions!=null && returnAppOpinions.size()>0) {
//			for (OpinionTypeDTO returnAppOpinion:returnAppOpinions) {
//				initOpinion(loanApplyCase,returnAppOpinion.getOpinionTypeCode(),loanChecking.getReturnAppOpinionContent());
//			}
//		}
//		//拒绝代码
//		List<OpinionTypeDTO> checkOpinionTypes = loanChecking.getCheckOpinionTypes();
//		if(checkOpinionTypes!=null && checkOpinionTypes.size()>0) {
//			for (OpinionTypeDTO checkOpinionType:checkOpinionTypes) {
//				initOpinion(loanApplyCase,checkOpinionType.getOpinionTypeCode(),loanChecking.getCheckOpinionContent());
//			}
//		}
//		return loanChecking;
//	}
//	private void initOpinion( LoanApplyCaseDTO loanApplyCase , String opinionTypeCode ,String remark) throws MarvelsBusinessException {
//		OpinionDTO opinion = new OpinionDTO();
//		opinion.setLoanId(loanApplyCase.getLoanId());
//		opinion.setCaseVersion(loanApplyCase.getCaseVersion());//在调用activiti之前调用记录
//		UserDTO user = CacheUtils.getCacheUser();
//		opinion.setCreatedBy(user == null ? "system" : user.getUserCode());
//		opinion.setNodeCode(loanApplyCase.getCurNodeCode());
//		opinion.setNodeName(loanApplyCase.getCurNodeName());
//		opinion.setOpinion(remark);
//		//String opinionTypeCode,String nodeCode,String patternCod
//		OpinionTypeDTO opinionTypeDTO = this.opinionTypeService.findOpinionType(opinionTypeCode,loanApplyCase.getCurNodeCode(),loanApplyCase.getPatternCode());
//		opinion.setOpinionClass(opinionTypeDTO.getOpinionClass());
//		opinion.setOpinionTypeApp(opinionTypeDTO.getOpinionTypeApp());
//		opinion.setOpinionTypeCode(opinionTypeDTO.getOpinionTypeCode());
//		opinion.setOpinionTypeName(opinionTypeDTO.getOpinionTypeName());
//		opinion.setUpdatedBy(user == null ? "system" : user.getUserCode());
//		opinionService.saveOpinion(opinion);
//	}
	//修改进件状态
	private void editLoanApplyInfo(McamLoanApplyInfoDTO loanApplyInfo , LoanApplyCaseDTO loanApplyCase) throws MarvelsBusinessException {
		String nodeCode = loanApplyCase.getCurNodeCode();
		//feign调用
		String stateId = stateDetailedService.queryStateDetailedByNodeCode(nodeCode);
		if(stateId == null) {
			throw new MarvelsBusinessException("新节点"+nodeCode+"无法获取进件节点号"+stateId);
		}
		String oldStatus = loanApplyInfo.getStatus();
		loanApplyInfo.setOldStatus(oldStatus);
		loanApplyInfo.setStatus(stateId);
		this.mcamLoanApplyInfoService.updateMcamLoanApplyInfoByLoanId(loanApplyInfo);
	}
	private McamLoanApplyInfoDTO getLoanApplyInfo(String loanId) throws MarvelsBusinessException {
		// 查询贷款信息
		if (loanId == null) {
			throw new MarvelsBusinessException("查询贷款信息条件不能为空" + loanId);
		}
		McamLoanApplyInfoDTO loanApplyInfo = this.mcamLoanApplyInfoService.findMcamLoanApplyInfo(loanId);
		if (loanApplyInfo == null) {
			throw new MarvelsBusinessException("贷款信息不存在loanId:" + loanId);
		}
		if ( !LoanStateConstant.Z01.equals(loanApplyInfo.getStatus())) {
			throw new MarvelsBusinessException("贷款信息状态不是征信复核阶段，请确认数据是否正确！status:"+loanApplyInfo.getStatus()+"\tloanId:" + loanId);
		}
		return loanApplyInfo;
	}
	private LoanApplyCaseDTO getLoanApplyCase(String loanId) throws MarvelsBusinessException {
		// 查询复核信息
		if (loanId == null) {
			throw new MarvelsBusinessException("查询征信阶段信息条件不能为空" + loanId);
		}
		LoanApplyCaseDTO loanApplyCase = loanApplyCaseDao.getEntityByLoanId(loanId);
		if (loanApplyCase == null) {
			throw new MarvelsBusinessException("工单不存在loanId:" + loanId);
		}
		if (!CaseNodeConstant.WOCHECKING.getCode().equals(loanApplyCase.getCurNodeCode())) {
			throw new MarvelsBusinessException("工单节点在" + loanApplyCase.getCurNodeCode() + "不正确,loanId:" + loanId);
		}
		return loanApplyCase;
	}

	@Override
	@Transactional(timeout = 30 ,rollbackFor=Exception.class)
	public LoanCheckingDTO complateChecking(LoanCheckingDTO loanChecking) throws MarvelsBusinessException {
		// 复核征信复核信息
		// 保存征信复核信息
		String loanId = loanChecking.getLoanId();
		LoanApplyCaseDTO loanApplyCase = getLoanApplyCase(loanId);
		McamLoanApplyInfoDTO loanApplyInfo = getLoanApplyInfo(loanId);

		//保存相关日志
		opinionService.saveOpinions(loanApplyCase,loanApplyInfo,loanChecking.getProcessResult()
				,loanChecking.getProcessOpinions(),loanChecking.getViolationOpinion(),loanChecking.getReturnAppOpinions(),loanChecking.getCheckOpinionTypes()
				,loanChecking.getCheckOpinionContent(),loanChecking.getViolationOptionContent(),loanChecking.getReturnAppOpinionContent());

		// 流转activiti
		CompleteProcessDTO completeProcessDTO = new CompleteProcessDTO();
		completeProcessDTO.setLoanId(loanId);
		ProcessApproveDTO processApproveDto = new ProcessApproveDTO();
		processApproveDto.setProcessResult(loanChecking.getProcessResult());
		completeProcessDTO.setProcessApproveDto(processApproveDto);
		loanApplyCase = processService.completeLoanApplyCase(completeProcessDTO);
		MarvelsLogUtil.getInstance().info("loanId：" + loanId + "，审核工作流完成，ProcessResult：" + loanChecking.getProcessResult());

		if("OK".equals(loanChecking.getProcessResult())){
			MarvelsLogUtil.getInstance().info("loanId：" + loanId + "，审核修改审核金额," + loanChecking.getApprovalAmount());
			//查找资金源信息
			FundSourceDTO fundSourceDTO= new FundSourceDTO();
			fundSourceDTO.setStatus("0");
			List<FundSourceDTO> fundSourceList = consumerFinancialApi.fundSourceInfo(fundSourceDTO);
			MarvelsLogUtil.getInstance().info("loanId：" + loanId + "，资金源列表：" + JSONObject.toJSONString(fundSourceList));
			if(fundSourceList == null || fundSourceList.size() == 0){
				throw new MarvelsBusinessException("未匹配到资金源信息:" + loanId);
			}
			//查找产品小类信息
			McptProductInfoDTO mcptProductInfoDTO = new McptProductInfoDTO();
			mcptProductInfoDTO.setTerm(String.valueOf(loanApplyInfo.getApplyTerms()));//默认先查询一期的
			mcptProductInfoDTO.setProductType(loanApplyInfo.getProductType());
			List<McptProductInfoDTO> productInfoList = productConsumerService.selectProductInfo(mcptProductInfoDTO);
			MarvelsLogUtil.getInstance().info("loanId：" + loanId + "，产品类型列表：" + JSONObject.toJSONString(productInfoList));
			if(productInfoList == null || productInfoList.size() == 0){
				throw new MarvelsBusinessException("未匹配到产品类别信息:" + loanId);
			}
			//插入审批进件需要字段
			McamLoanApplyInfoDTO newLoanApplyInfo = new McamLoanApplyInfoDTO();
			newLoanApplyInfo.setLoanId(loanId);
			newLoanApplyInfo.setProductCode(productInfoList.get(0).getProductCode());
			newLoanApplyInfo.setFundCode(fundSourceList.get(0).getFundCode());
			newLoanApplyInfo.setFundName(fundSourceList.get(0).getFundName());
			newLoanApplyInfo.setPrincipalAmtAct(loanChecking.getApprovalAmount());
			this.mcamLoanApplyInfoService.updateMcamLoanApplyInfoByLoanId(newLoanApplyInfo);
			//更新进件表资金源、核定金额、产品小类字段信息
			AcLoanApplyInfo acLoanApplyInfo = new AcLoanApplyInfo();
			acLoanApplyInfo.setLoanId(loanId);
			acLoanApplyInfo.setProductId(newLoanApplyInfo.getProductCode());
			acLoanApplyInfo.setFundSource(Integer.getInteger(newLoanApplyInfo.getFundCode()));
			acLoanApplyInfo.setLoanMoneyAct(newLoanApplyInfo.getPrincipalAmtAct());
			loanInfoIDragonService.input(acLoanApplyInfo);
			MarvelsLogUtil.getInstance().info("loanId：" + loanId + "，审核修改审核金额完成");
		}else{
			acLoanApplyNodeService.insertSelective(loanId, ApplyNode.REVIEW_REFUSE);
			MarvelsLogUtil.getInstance().info("loanId：" + loanId + "，审核拒绝后置流转节点完成");
		}
		modifyStatus(loanApplyInfo,loanApplyCase, loanChecking);
		MarvelsLogUtil.getInstance().info("loanId：" + loanId + "，审批节点完成");
		return loanChecking;
	}
	//征信 状态流转
	private void modifyStatus(McamLoanApplyInfoDTO loanApplyInfo,LoanApplyCaseDTO loanApplyCase, LoanCheckingDTO loanChecking)throws MarvelsBusinessException {
		String status = loanApplyInfo.getStatus();
		String nextStatus = "";
		String curNodeCode = loanApplyCase.getCurNodeCode();
		String assignee = loanApplyCase.getAssignee();
		if(CaseNodeConstant.WOAPPROVAL.getCode().equals(curNodeCode)) {
			if(StringUtil.isEmpty(assignee)) {
				nextStatus = LoanStateConstant.S01;
			}else {
				nextStatus = LoanStateConstant.S00;
			}
			mcamLoanApplyInfoCommonService.updateMcamLoanApplyInfoStatusByLoanId(loanApplyInfo.getLoanId(), nextStatus, status, null);
		}else if(CaseNodeConstant.WOEND.getCode().equals(curNodeCode)) {		//线上产品走线下审批完结
			//modifyOnLine(loanApplyInfo, loanChecking);
			modifyToSign(loanApplyInfo,loanChecking);
		}
	}


	//线上产品走线下审批完结
	private void modifyToSign(McamLoanApplyInfoDTO loanApplyInfo, LoanCheckingDTO loanChecking) throws MarvelsBusinessException {
		try {
			String nextStatus = "";
			//拒绝
			if(MarvelsConstant.PROCESS_RESULT_REFUSE.equals(loanChecking.getProcessResult())) {
				nextStatus = LoanStateConstant.CR0;
			}else {
				nextStatus = LoanStateConstant.P04;
			}
			String status = loanApplyInfo.getStatus();
			mcamLoanApplyInfoCommonService.updateMcamLoanApplyInfoStatusByLoanId(loanApplyInfo.getLoanId(), nextStatus, status, null);

			if(StringUtils.equalsIgnoreCase(nextStatus, LoanStateConstant.P04)) {
				acLoanApplyNodeService.insertSelective(loanApplyInfo.getLoanId(), ApplyNode.REVIEW_SUCCESS);
				MarvelsLogUtil.getInstance().info("loanId：" + loanApplyInfo.getLoanId() + "，审核后置通过流转节点完成");
//				clientAppService.confirmLoanApply(loanApplyInfo.getLoanId());
			}
		}catch(Exception ex) {
			throw new MarvelsBusinessException("更新审批通过状态失败！");
		}
	}

	//线上产品走线下审批完结
	private void modifyOnLine(McamLoanApplyInfoDTO loanApplyInfo, LoanCheckingDTO loanChecking) throws MarvelsBusinessException {
		String nextStatus = "";
		//拒绝
		if(MarvelsConstant.PROCESS_RESULT_REFUSE.equals(loanChecking.getProcessResult())) {
			nextStatus = LoanStateConstant.CR0;
		}else {
			nextStatus = LoanStateConstant.P05;
		}
		String status = loanApplyInfo.getStatus();
		mcamLoanApplyInfoCommonService.updateMcamLoanApplyInfoStatusByLoanId(loanApplyInfo.getLoanId(), nextStatus, status, null);
	}

}
